package crivia.eca.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import crivia.c.CarryIO;
import crivia.c.a.KeyLink;
import crivia.c.carry.RelationKey;
import crivia.c.carry.ValueField;
import crivia.c.exception.CarryIOFail;
import crivia.db.common.SQL;
import crivia.ecp.a.ECC;
import crivia.ecp.common.ECR;
import crivia.ecp.common.EcologyDB;

/**
 * Workflow Data Transform Rule.<br/>
 * For Request.
 * @author Mana
 */
public class WDTR extends ECC {
	
	static {
		
		if (! createTable(WDTR.class, true)){
			throw new CarryIOFail("Data Base Table Create Fail.");
		}
		
	}
	
	//Workflow > Table Index > Field > Rule.
	private static Map<String, List<Map<String , WDTR>>> WDTRs =
		new HashMap<String, List<Map<String,WDTR>>>();
	private static synchronized void loadWDTR(String workflow,int tableIndex,String field){
		if (true
		&& WDTRs.containsKey(workflow)
		&& WDTRs.get(workflow).size() > tableIndex
		&& WDTRs.get(workflow).get(tableIndex).containsKey(field.toLowerCase())){
			return;
		}
		WDTR wdtr = new WDTR();
		wdtr = SQL.one(EcologyDB.db(), WDTR.class, false
				, SQL.cd.equals(wdtr.dbKey("workflow"), workflow)
				, SQL.cd.equals(wdtr.dbKey("tableIndex"), tableIndex)
				, SQL.cd.or(
						SQL.cd.equals(wdtr.dbKey("field"), field)
						,SQL.cd.equals(wdtr.dbKey("field"), field.toLowerCase())
						,SQL.cd.equals(wdtr.dbKey("field"), field.toUpperCase())));
		if (!WDTRs.containsKey(workflow)){
			WDTRs.put(workflow, new ArrayList<Map<String,WDTR>>());
		}
		while (WDTRs.get(workflow).size() < tableIndex + 1){
			WDTRs.get(workflow).add(new HashMap<String, WDTR>());
		}
		if (null != wdtr && ECR.hasCondition(wdtr.getNickField())){
			WDTRs.get(workflow).get(tableIndex).put((
					"XML-"+wdtr.getNickField()
				).toLowerCase(), wdtr);
		} else {
			WDTRs.get(workflow).get(tableIndex).put(field.toLowerCase(), wdtr);
		}
	}
	public static WDTR wdtr(String workflow,int tableIndex,String field){
		if (false
		|| !WDTRs.containsKey(workflow)
		|| WDTRs.get(workflow).size() < tableIndex + 1
		|| !WDTRs.get(workflow).get(tableIndex).containsKey(field.toLowerCase())){
			loadWDTR(workflow, tableIndex, field);
		}
		WDTR wdtr = WDTRs.get(workflow).get(tableIndex).get(field.toLowerCase());
		if (null != wdtr && "Y".equals(wdtr.getAble())){
			return wdtr;
		}
		return null;
	}
	public static void wdtr(WDTR wdtr){
		if (false
		|| !ECR.hasCondition(wdtr.workflow)
		|| !ECR.hasCondition(wdtr.field)){
			return;
		}
		if (!WDTRs.containsKey(wdtr.workflow)){
			WDTRs.put(wdtr.workflow, new ArrayList<Map<String,WDTR>>());
		}
		while (WDTRs.get(wdtr.workflow).size() < wdtr.tableIndex + 1){
			WDTRs.get(wdtr.workflow).add(new HashMap<String, WDTR>());
		}
		WDTRs.get(wdtr.workflow).get(wdtr.tableIndex).put(wdtr.field.toLowerCase(), wdtr);
	}
	public static void wdtrClean(String workflow,int tableIndex,String field){
		if (false
		|| !WDTRs.containsKey(workflow)
		|| WDTRs.get(workflow).size() < tableIndex + 1
		|| !WDTRs.get(workflow).get(tableIndex).containsKey(field.toLowerCase())){
			return;
		}
		WDTRs.get(workflow).get(tableIndex).put(field, null);
	}





	private java.lang.String id;
	public java.lang.String getId(){
		return id;
	}
	public crivia.eca.service.WDTR setId(java.lang.String id){
		this.id = id;
		return this;
	}

	private java.lang.String workflow;
	public java.lang.String getWorkflow(){
		return workflow;
	}
	public crivia.eca.service.WDTR setWorkflow(java.lang.String workflow){
		this.workflow = workflow;
		return this;
	}

	private java.lang.String workflowName;
	public java.lang.String getWorkflowName(){
		return workflowName;
	}
	public crivia.eca.service.WDTR setWorkflowName(java.lang.String workflowName){
		this.workflowName = workflowName;
		return this;
	}

	private int tableIndex;
	public int getTableIndex(){
		return tableIndex;
	}
	public crivia.eca.service.WDTR setTableIndex(int tableIndex){
		this.tableIndex = tableIndex;
		return this;
	}

	private java.lang.String field;
	public java.lang.String getField(){
		return field;
	}
	public crivia.eca.service.WDTR setField(java.lang.String field){
		this.field = ECR.hasCondition(field)?field.toLowerCase():field;
		return this;
	}

	private java.lang.String nickField;
	public java.lang.String getNickField(){
		return nickField;
	}
	public crivia.eca.service.WDTR setNickField(java.lang.String nickField){
		this.nickField = nickField;
		return this;
	}

	private java.lang.String able = "Y";
	public java.lang.String getAble(){
		return able;
	}
	public crivia.eca.service.WDTR setAble(java.lang.String able){
		this.able = able;
		return this;
	}

	private java.lang.String invokeClass;
	public java.lang.String getInvokeClass(){
		return invokeClass;
	}
	public crivia.eca.service.WDTR setInvokeClass(java.lang.String invokeClass){
		this.invokeClass = invokeClass;
		return this;
	}

	private java.lang.String invokeMethod;
	public java.lang.String getInvokeMethod(){
		return invokeMethod;
	}
	public crivia.eca.service.WDTR setInvokeMethod(java.lang.String invokeMethod){
		this.invokeMethod = invokeMethod;
		return this;
	}

	private java.lang.String transformSQL;
	public java.lang.String getTransformSQL(){
		return transformSQL;
	}
	public crivia.eca.service.WDTR setTransformSQL(java.lang.String transformSQL){
		this.transformSQL = transformSQL;
		return this;
	}





	@Override
	public void keyLinks(List<KeyLink> keyLinks) {
		keyLinks.add(ValueField.c2d("workflow"));
		keyLinks.add(RelationKey.fieldToKey("workflowName", "workflow"
			, "workflow_base", "workflowName", "id"));
		keyLinks.add(ValueField.c2d("tableIndex",int.class));
		keyLinks.add(ValueField.c2d("field"));
		keyLinks.add(ValueField.c2d("nickField"));
		keyLinks.add(ValueField.c2d("able"));
		keyLinks.add(ValueField.c2d("invokeClass"));
		keyLinks.add(ValueField.c2d("invokeMethod"));
		keyLinks.add(ValueField.c2d("transformSQL"));
	}
	
	@Override
	public ValueField primaryKey() {
		return ValueField.c2d("id");
	}

	@Override
	public String tableName() {
		return "Crivia_Wf_Dt_Trsfm_Rule";
	}

	public String transform(String s , String w){
		if (ECR.hasCondition(invokeClass) && ECR.hasCondition(invokeMethod)){
//			try {
//				Class<?> t = Class.forName(invokeClass);
//				Object r = CarryIO.getInstance(t);
//				return String.valueOf(t.getMethod(invokeMethod
//						, String.class , String.class , String.class).invoke(r, s, w, u));
//			} catch (Throwable e) {}
			try {
				Class<?> t = Class.forName(invokeClass);
				Object r = CarryIO.getInstance(t);
				return String.valueOf(t.getMethod(invokeMethod
						, String.class , String.class).invoke(r, s, w));
			} catch (Throwable e) {
				try {
					crivia.txt.common.Logger.logException("TransformFail.", e);
				} catch (Throwable t) {}
			}
			try {
				Class<?> t = Class.forName(invokeClass);
				Object r = CarryIO.getInstance(t);
				return String.valueOf(t.getMethod(invokeMethod
						, String.class).invoke(r, s));
			} catch (Throwable e) {
				try {
					crivia.txt.common.Logger.logException("TransformFail.", e);
				} catch (Throwable t) {}
			}
		} else if (ECR.hasCondition(transformSQL)){
			try {
				return SQL.select(
					SQL.sql.array(transformSQL, s),EcologyDB.db()).get();
			} catch (Throwable e) {}
		}
		return s;
	}



}
